package uk.ac.bath.genetic.plant;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.ac.bath.genetic.bool.LogicalMachine;
import uk.ac.bath.genetic.base.Point;
import uk.ac.bath.genetic.base.Cell;
import uk.ac.bath.genetic.mover.Environment;

import  uk.ac.bath.util.*;
import java.util.*;
import uk.ac.bath.genetic.base.EnvironmentIF;


public class PlantCell extends Cell  {


    public static Vector<Tweakable> tweaks=new Vector<Tweakable>();
    public static TweakableDouble cellMutateProb    = 
	new TweakableDouble(tweaks,0.0,1.0,0.001,0.0001,"MutateProb");

    public static TweakableInt tickCost  =  
	new TweakableInt(tweaks,0,200,10,"TickCost"); 

    public static TweakableInt maxBite  =  
	new TweakableInt(tweaks,0,200,30,"MaxBite");

    public static TweakableInt initialFitness  
	= new TweakableInt(tweaks,0,1000,60,"InitialFitness");

    public static TweakableInt maxOperatorsPerCell =
	 new TweakableInt(tweaks,10,1000,20,"MaxMachineSize");

    public static TweakableDouble cloneCostFact    = 
	new TweakableDouble(tweaks,0.0,10.0,1.0,0.01,"CloneCostPerOp");


    public Collection<Tweakable> getTweaks() { return tweaks;}

    final public static int minOperatorsPerCell=5;

    double foodReserve;

    public PlantCell(LogicalMachine machine,
		     Point point,
		     double fitness,
		     int id,int generation,int mutation,String tag) {
	super(machine,point,fitness,id,generation,mutation,tag);
    }

     public  PlantCell () {
	super(null,null,0,0,-1,0,"MCT Proto");
     }



    public Cell cloneToPoint(Point p,double fitness) {
        try {
            return new PlantCell((LogicalMachine) (machine.clone()), p, fitness, id_, generation + 1, mutationCount, tag);
        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(PlantCell.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void tickImpl(EnvironmentIF env1) {
	
	PlantEnvironment env = (PlantEnvironment)env1;

	age++;
	if (fitness <= 0) return;

 	if (at(-1).isOn()) {
	    Point pc = env.randomEmptyAdjacent(point);
	    if (pc != null) {
		double cloneFitness=Math.min(at(-2).doubleValue(),fitness);
		Cell newCell = cloneToPoint(pc,cloneFitness);
		fitness -= cloneFitness;
		fitness -= cloneCostFact.doubleValue()*size;
		if( MyRandom.nextDouble() < 
		    cellMutateProb.getNumber().doubleValue()) {
		  //  newCell.mutate(env.pallete);
           // newCell.mutate();
            env.mutateCell(this);
		}
		env.addCell(newCell);
	    }
	}
	
// 	foodReserve  += env.eatFoodAt(point,maxBite.getNumber().doubleValue());

// 	double light = env.getLightAt(point);

// 	double denergy = Math.min(light,foodReserve);

// 	foodReserve    -= denergy;
// 	fitness        += denergy - tickCost.getNumber().doubleValue();
	fitness        += env.eatFoodAt(point,maxBite.getNumber().doubleValue())	    - tickCost.getNumber().doubleValue();
	if (fitness > 0.0)
	    at(0).set(fitness);
	else 
	    at(0).set(0.0);
	//	at(1).set(env.getLightAt(point));
	machine.tick();
    }
    
    public String getTag() {
	if (mutationCount == 0) return "P"+id_;
	else return "P"+id_+"#"+mutationCount;
    }
    


}




